package com.cxyd.modules.wcs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cxyd.common.constant.RcsConstants;
import com.cxyd.common.constant.WcsConstants;
import com.cxyd.common.page.PageData;
import com.cxyd.common.service.impl.CrudServiceImpl;
import com.cxyd.common.utils.ConvertUtils;
import com.cxyd.modules.log.service.SysLogWorkService;
import com.cxyd.modules.wcs.dao.AgvTrkHkDao;
import com.cxyd.modules.wcs.dao.PostTcpDao;
import com.cxyd.modules.wcs.dto.PostTcpDTO;
import com.cxyd.modules.wcs.entity.AgvTrkHkEntity;
import com.cxyd.modules.wcs.entity.PostTcpEntity;
import com.cxyd.modules.wcs.entity.TcpResponseEntity;
import com.cxyd.modules.wcs.service.PostTcpService;
import com.cxyd.modules.wcs.service.TcpResponseService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.Map;

/**
 * 下发指令
 *
 * @author Cycle gengruyi01@163.com
 * @since 1.0.0 2022-11-04
 */
@Service
public class PostTcpServiceImpl extends CrudServiceImpl<PostTcpDao, PostTcpEntity, PostTcpDTO> implements PostTcpService {
    @Resource
    private AgvTrkHkDao agvTrkHkDao;
    @Resource
    private TcpResponseService tcpResponseService;
    @Resource
    private SysLogWorkService logWorkService;

    public PostTcpServiceImpl() {
    }

    @Override
    public PageData<PostTcpDTO> page(Map<String, Object> params) {
        IPage<PostTcpEntity> page = baseDao.selectPage(
                getPage(params, "update_date", false),
                getWrapper(params)
        );
        return getPageData(page, PostTcpDTO.class);
    }

    @Override
    public QueryWrapper<PostTcpEntity> getWrapper(Map<String, Object> params) {
        String contNo = (String) params.get("contNo");
        QueryWrapper<PostTcpEntity> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(contNo), "cont_no", contNo);
        return wrapper;
    }

    @Override
    public PostTcpDTO getPostTcp() {
        QueryWrapper<PostTcpEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(PostTcpEntity::getPostSt, WcsConstants.POST_STATUS_START)
                .orderBy(true, true, PostTcpEntity::getCreateDate)
                .last("limit 1");
        PostTcpEntity entity = baseDao.selectOne(qw);
//        对待发送消息进行判定,如果内容为空等则不发送且标识异常
        if (entity == null) {
            return null;
        }
        if (StringUtils.isBlank(entity.getPostMsg())) {
            entity.setPostSt(WcsConstants.POST_STATUS_ERROR);
            entity.setAckMsg("PostMsg is null or empty!");
            entity.setUpdateDate(new Date());
            baseDao.updateById(entity);
            return null;
        }
        return ConvertUtils.sourceToTarget(entity, PostTcpDTO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void postTcpHandle(PostTcpDTO dto, String response) {
        String pCode = WcsConstants.PROC_CODE_SUCCESS;
        String pMsg = "与设备[" + dto.getDvcNo() + "]完成完全请求!交互结果[" + response + "]";
        int status = WcsConstants.POST_STATUS_START;
//        判断交互是否成功，需要判断response是否与请求类型匹配
        TcpResponseEntity correctResponse = tcpResponseService.getMappingByNoticeType(dto.getNoticeType(), dto.getTaskTyp());
        if (correctResponse == null || !response.contains(correctResponse.getResponseMsg())) {
//            status = WcsConstants.POST_STATUS_ERROR;
//            信息下发后收到异常反馈
            pCode = "PostTcpHandle_001";
            pMsg = "与机台[" + dto.getDvcNo() + "]安全交互异常!响应消息与请求类型不匹配!";
        } else {
            status = WcsConstants.POST_STATUS_SUCCESS;
        }
        //        开始时间-start
        Instant start = Instant.now();
//        1.更新post_wms记录状态
        PostTcpEntity PostTcpEntity = baseDao.selectById(dto.getPostId());
//        核验类型是[通知]or[完成]
        PostTcpEntity.setPostSt(status);
        PostTcpEntity.setAckMsg(response);
        PostTcpEntity.setUpdater(WcsConstants.WCS_USER_ID);
        PostTcpEntity.setUpdateDate(new Date());
        baseDao.updateById(PostTcpEntity);
//        机台数据交互成功则更新agv_trk_hk表,使其任务继续(Finished无需任务继续)
        if (status == WcsConstants.POST_STATUS_SUCCESS && !response.contains(WcsConstants.TCP_MSG_FINISHED)) {
//            获取agv_trk_hk表中对应机台的任务
            AgvTrkHkEntity agvTask = agvTrkHkDao.getTaskByTaskCode(dto.getTaskCode());
            if (agvTask == null) {
                return;
            }
//            更新任务继续
            agvTask.setStatus(RcsConstants.HK_STATUS_CONTINUE);
            agvTask.setData("收到机台反馈[" + response + "]可继续进行下一步动作");
            agvTask.setUpdater(WcsConstants.WCS_USER_ID);
            agvTask.setUpdateDate(new Date());
            agvTrkHkDao.updateById(agvTask);
        }
        //        结束时间-end
        Instant end = Instant.now();
        String workName = "[流程-TCP]安全交互";
        String workProc = "PostTcpServiceImpl.PostTcpHandle";
//        计算耗时
        Duration times = Duration.between(start, end);
        logWorkService.workLogging(workName, dto.getContNo(), pCode, pMsg, "", workProc, WcsConstants.WCS_USER_NAME, times.toMillis());
    }

    @Override
    public void backupPostTcpByTaskCode(String taskCode) {
        if (StringUtils.isBlank(taskCode)) {
            return;
        }
        baseDao.backupPostTcpByTaskCode(taskCode);
        baseDao.deletePostTcpByTaskCode(taskCode);
    }
}